package com.settlement.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.settlement.system.common.util.DateUtils;
import com.settlement.system.common.util.StringUtils;
import com.settlement.system.mapper.SysLockDailyRecordMapper;
import com.settlement.system.model.entity.SysLockDailyRecord;
import com.settlement.system.model.entity.SysPlatform;
import com.settlement.system.model.entity.SysStore;
import com.settlement.system.model.form.SysLockDailyRecordForm;
import com.settlement.system.model.query.SysLockDailyRecordQuery;
import com.settlement.system.model.vo.SysLockDailyRecordImportVo;
import com.settlement.system.model.vo.SysLockSummaryRecord;
import com.settlement.system.service.SysLockDailyRecordService;
import com.settlement.system.service.SysPlatformService;
import com.settlement.system.service.SysStoreService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 月度锁账日报表 服务实现类
 * </p>
 *
 * @author huangrensen
 * @since 2024-08-19
 */
@Service
@RequiredArgsConstructor
public class SysLockDailyRecordServiceImpl extends ServiceImpl<SysLockDailyRecordMapper, SysLockDailyRecord> implements SysLockDailyRecordService {

    private final SysStoreService sysStoreService;

    private final SysPlatformService sysPlatformService;

    @Override
    public Page<SysLockDailyRecord> getPage(SysLockDailyRecordQuery queryParams) {
        // 查询参数
        int pageNum = queryParams.getPageNum();
        int pageSize = queryParams.getPageSize();
        // 查询数据
        Page<SysLockDailyRecord> page = new Page<>(pageNum, pageSize);
        this.baseMapper.getPage(page, queryParams);
        if (page.getRecords().size() > 0) {
            SysStore sysStore;
            SysPlatform sysPlatform;
            for (SysLockDailyRecord record : page.getRecords()) {
                sysPlatform = sysPlatformService.getById(record.getPlatformId());
                if (Objects.nonNull(sysPlatform)) {
                    record.setPlatformName(sysPlatform.getReconciliationSystemName());
                }
                sysStore = sysStoreService.getById(record.getStoreId());
                if (Objects.nonNull(sysStore)) {
                    record.setStoreName(sysStore.getCommercePlatformStoreName());
                }
                // 收入金额（发货金额-退货金额）
                record.calculateReceiveAmount();
            }
        }
        return page;
    }

    @Override
    public boolean saveSysLockDailyRecord(SysLockDailyRecordForm sysLockDailyRecordForm) {
        SysLockDailyRecord sysLockDailyRecord = new SysLockDailyRecord();
        BeanUtils.copyProperties(sysLockDailyRecordForm, sysLockDailyRecord);
        sysLockDailyRecord.setCreateTime(null);
        return this.saveOrUpdate(sysLockDailyRecord);
    }

    @Override
    public SysLockDailyRecordForm getSysLockDailyRecordFormData(Long id) {
        SysLockDailyRecord sysLockDailyRecord = this.getById(id);
        SysLockDailyRecordForm sysLockDailyRecordForm = new SysLockDailyRecordForm();
        BeanUtils.copyProperties(sysLockDailyRecord, sysLockDailyRecordForm);
        return sysLockDailyRecordForm;
    }

    @Override
    public boolean deleteSysLockDailyRecord(String ids) {
        Assert.isTrue(StringUtils.hasText(ids), "删除的数据为空");
        List<Long> idArray = Arrays.stream(ids.split(",")).map(Long::parseLong).collect(Collectors.toList());
        return this.removeByIds(idArray);
    }

    @Override
    public void importData(List<SysLockDailyRecordImportVo> voList) {
        List<SysLockDailyRecord> sysLockDailyRecordList = new ArrayList<>();
        for (SysLockDailyRecordImportVo importVo : voList) {
            SysLockDailyRecord sysLockDailyRecord = new SysLockDailyRecord();
            BeanUtils.copyProperties(importVo, sysLockDailyRecord);
            sysLockDailyRecordList.add(sysLockDailyRecord);
        }
        this.saveOrUpdateBatch(sysLockDailyRecordList);
    }

    @Override
    public List<SysLockDailyRecordImportVo> findByIds(String idsStr) {
        if (!StringUtils.hasText(idsStr)) {
            return new ArrayList<>();
        }
        List<Long> ids = Arrays.stream(idsStr.split(",")).map(Long::parseLong).collect(Collectors.toList());
        List<SysLockDailyRecord> sysLockDailyRecordList = this.getBaseMapper().selectBatchIds(ids);
        List<SysLockDailyRecordImportVo> voList = new ArrayList<>();
        for (SysLockDailyRecord sysLockDailyRecord : sysLockDailyRecordList) {
            SysLockDailyRecordImportVo vo = new SysLockDailyRecordImportVo();
            BeanUtils.copyProperties(sysLockDailyRecord, vo);
            voList.add(vo);
        }
        return voList;
    }

    @Override
    public List<SysLockSummaryRecord> getSummaryRecord(SysLockDailyRecordQuery queryParams) {
        List<SysLockSummaryRecord> recordList = new ArrayList<>();
        if (!StringUtils.hasText(queryParams.getBillMonth())) {
            return recordList;
        }
        LocalDateTime billTime = DateUtils.convertStringToLocalDateTime(queryParams.getBillMonth() + "-01");
        if (Objects.isNull(billTime)) {
            return recordList;
        }
        // 查询店铺
        SysPlatform sysPlatform;
        List<SysStore> storeList;
        if (Objects.nonNull(queryParams.getPlatformId())) {
            sysPlatform = sysPlatformService.getById(queryParams.getPlatformId());
            storeList = sysStoreService.list(new LambdaQueryWrapper<SysStore>().eq(SysStore::getStoreKey, sysPlatform.getPlatformKey()).eq(Objects.nonNull(queryParams.getStoreId()), SysStore::getId, queryParams.getStoreId()));
        }else{
            storeList = sysStoreService.list(new LambdaQueryWrapper<SysStore>().eq(Objects.nonNull(queryParams.getStoreId()), SysStore::getId, queryParams.getStoreId()));
        }
        // 查询月度锁账日报表数据
        LocalDate startDate = billTime.minusMonths(1).toLocalDate().atStartOfDay().toLocalDate();
        LocalDate endDate = billTime.plusMonths(1).toLocalDate().atStartOfDay().toLocalDate();
        List<SysLockDailyRecord> lockDailyRecordList = list(new LambdaQueryWrapper<SysLockDailyRecord>()
                .eq(Objects.nonNull(queryParams.getPlatformId()), SysLockDailyRecord::getPlatformId, queryParams.getPlatformId())
                .eq(Objects.nonNull(queryParams.getStoreId()), SysLockDailyRecord::getStoreId, queryParams.getStoreId())
                .ge(SysLockDailyRecord::getBusinessDate, startDate).lt(SysLockDailyRecord::getBusinessDate, endDate));
        SysLockSummaryRecord record;
        SysLockSummaryRecord.Item item;
        // 当前的月份
        String currentBillMonth = DateUtils.formatDate(LocalDateTime.now());
        String status = Objects.equals(currentBillMonth, queryParams.getBillMonth().replaceAll("-", "")) ? "未锁账" : "已锁账";
        String lastBillMonth = DateUtils.formatDate(startDate.atStartOfDay());
        List<SysLockDailyRecord> filterLockDailyRecordList;
        for (SysStore sysStore : storeList) {
            record = new SysLockSummaryRecord();
            record.setStoreName(sysStore.getCommercePlatformStoreName());
            sysPlatform = sysPlatformService.getByPlatformKey(sysStore.getStoreKey());
            if (Objects.nonNull(sysPlatform)) {
                record.setPlatformName(sysPlatform.getReconciliationSystemName());
            }
            // 周期
            record.setBillMonth(queryParams.getBillMonth());
            // 锁账状态"
            // 1、已锁账/未锁帐
            //2、锁帐状态指的是本期是否锁帐。
            //3、如果周期是当月的情况，显示未锁帐；如果周期不是当月，显示已锁帐。"
            record.setStatus(status);
            // 期初数据：统计查询周期上一个月的数据
            filterLockDailyRecordList = lockDailyRecordList.stream().filter(obj -> Objects.equals(sysStore.getId(), obj.getStoreId()) && Objects.equals(lastBillMonth, DateUtils.formatDate(obj.getBusinessDate().atStartOfDay()))).toList();
            record.setBeginItem(buildItem(filterLockDailyRecordList));
            // 本期发生：统计查询周期月份的数据
            filterLockDailyRecordList = lockDailyRecordList.stream().filter(obj -> Objects.equals(sysStore.getId(), obj.getStoreId()) && Objects.equals(queryParams.getBillMonth().replaceAll("-", ""), DateUtils.formatDate(obj.getBusinessDate().atStartOfDay()))).toList();
            record.setCurrentItem(buildItem(filterLockDailyRecordList));
            // 期末数据
            item = new SysLockSummaryRecord.Item();
            // 发货金额：期初发货金额 + 本期发货金额
            item.setSendAmount(record.getBeginItem().getSendAmount().add(record.getCurrentItem().getSendAmount()));
            // 退货金额：期初退货金额 + 本期退货金额
            item.setReturnAmount(record.getBeginItem().getReturnAmount().add(record.getCurrentItem().getReturnAmount()));
            // 收入金额：发货金额 - 退货金额
            item.setReceiveAmount(item.getSendAmount().subtract(item.getReturnAmount()));
            // 应收账款余额：等于 本期的应收账款余额
            item.setReceiveBillAmount(record.getCurrentItem().getReceiveBillAmount());
            record.setEndItem(item);
            recordList.add(record);
        }
        return recordList;
    }

    private SysLockSummaryRecord.Item buildItem(List<SysLockDailyRecord> filterLockDailyRecordList) {
        SysLockSummaryRecord.Item item = new SysLockSummaryRecord.Item();
        // 本期发生-发货金额
        item.setSendAmount(filterLockDailyRecordList.stream().map(SysLockDailyRecord::getSendAmount).reduce(BigDecimal.ZERO, BigDecimal::add));
        // 本期发生-退货金额
        item.setReturnAmount(filterLockDailyRecordList.stream().map(SysLockDailyRecord::getReturnAmount).reduce(BigDecimal.ZERO, BigDecimal::add));
        // 本期发生-收入金额：发货金额 - 退货金额
        item.setReceiveAmount(item.getSendAmount().subtract(item.getReturnAmount()));
        // 本期发生-应收账款余额
        item.setReceiveBillAmount(filterLockDailyRecordList.stream().map(SysLockDailyRecord::getReceiveBillAmount).reduce(BigDecimal.ZERO, BigDecimal::add));
        return item;
    }
}
